package demo.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import demo.Result;
import demo.dto.*;
import demo.entity.Company;
import demo.entity.Department;
import demo.service.CompanyService;
import demo.service.DepartmentService;
import demo.service.ScoreService;
import demo.service.UserCompanyService;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * 部门管理 Controller
 *
 * @author 肖溥博文
 * @version 1.4
 */
@RestController
public class DepartmentController {
    @Autowired
    DepartmentService departmentService;
    @Autowired
    CompanyService companyService;
    @Autowired
    UserCompanyService userCompanyService;
    @Autowired
    CommentController commentController;
    @Autowired
    ScoreService scoreService;

    /**
     * 按传入的 公司 id 获取公司现存部门
     *
     * @param company 公司对象，必须含有 companyId
     * @return 结果对象，包含一个列举该公司所有部门的数组
     */
    @PostMapping("/listDepartments")
    @RequiresAuthentication
    public Result listDepartments(@RequestBody Company company) {
        Result departments = departmentService.listDepartments(company.getCompanyId());
        List<Department> departmentList = (List<Department>) departments.getData();
        List<ResponseDepartmentsDto> responseDepartmentsDtoList = new ArrayList<>();

        for (Department department : departmentList) {
            ResponseDepartmentsDto responseDepartmentsDto = new ResponseDepartmentsDto();
            BeanUtil.copyProperties(department, responseDepartmentsDto);

            Double score = (Double) commentController.getAverageScoreOfDepartment(department).getData();
            responseDepartmentsDto.setAverageScore(score);

            Long count = (Long) userCompanyService.countEmployeesByDepartmentId(department.getDepartmentId()).getData();
            responseDepartmentsDto.setCount(count);

            responseDepartmentsDtoList.add(responseDepartmentsDto);
        }
        return Result.success("部门查询成功", responseDepartmentsDtoList);
    }

    /**
     * 获取各部门的平均得分
     *
     * @param requestWithLongDto 必须包含一个公司 id
     * @return 结果对象，包含折线图数据
     */
    @PostMapping("/getScoresOfDepartments")
    public Result getScoresOfDepartments(@Validated @RequestBody RequestWithLongDto requestWithLongDto) {

        Long companyId = requestWithLongDto.getId();
        Result findCompanyResult = companyService.find(companyId);
        if (findCompanyResult.getCode() != 200) {
            return Result.error("公司不存在");
        }

        Result departmentsResult = departmentService.listDepartments(companyId);
        List<Department> departments = (List<Department>) departmentsResult.getData();

        List<String> details = new ArrayList<>();
        List<Double> values = new ArrayList<>();
        ResponseWithChartDataDto responseWithChartDataDto = new ResponseWithChartDataDto();

        for (Department department : departments) {
            Double score = (Double) commentController.getAverageScoreOfDepartment(department).getData();
            details.add(department.getDepartmentName());
            values.add(score);
        }

        responseWithChartDataDto.setDetails(details);
        responseWithChartDataDto.setData(values);

        return Result.success("查询所有部门的平均评分成功", responseWithChartDataDto);
    }

    /**
     * 按传入的 公司 id 和部门名添加部门
     *
     * @param requestAddDepartmentDto 数据对象，必须含有 companyId 和 departmentName
     * @return 结果对象
     */
    @PostMapping("/addDepartment")
    @RequiresAuthentication
    @RequiresRoles("HR")
    public Result addDepartment(@Validated @RequestBody RequestAddDepartmentDto requestAddDepartmentDto) {
        Long companyId = requestAddDepartmentDto.getCompanyId();
        if (companyService.find(companyId).getCode() != 200) {
            return Result.error("公司不存在，无法添加部门");
        }

        String departmentName = requestAddDepartmentDto.getDepartmentName();
        if (departmentService.findByCompanyIdAndDepartmentNameAndUsable(companyId, departmentName).getCode() == 200) {
            return Result.error("已存在同名部门，无法添加部门");
        }

        return departmentService.add(requestAddDepartmentDto.getDepartmentName(), requestAddDepartmentDto.getCompanyId());
    }

    /**
     * 在用户输入新的部门名时，检测部门是否存在
     *
     * @param requestAddDepartmentDto 数据对象，必须含有 companyId 和 departmentName
     * @return 结果对象
     */
    @PostMapping("/isDepartmentExistWhenAdding")
    @RequiresAuthentication
    @RequiresRoles("HR")
    public Result isDepartmentExistWhenAdding(@Validated @RequestBody RequestAddDepartmentDto requestAddDepartmentDto) {
        if (requestAddDepartmentDto.getCompanyId() == null) {
            return Result.error("公司 id 为空");
        }

        Boolean isFound = departmentService.findByCompanyIdAndDepartmentName(
            requestAddDepartmentDto.getCompanyId(),
            requestAddDepartmentDto.getDepartmentName()
        );
        return isFound ? Result.error("部门已存在") : Result.success("部门名未被占用");
    }

    /**
     * 按传入的 departmentId 删除部门
     *
     * @param department 部门对象，必须包含 departmentId
     * @return 结果对象
     */
    @PostMapping("/deleteDepartment")
    @RequiresAuthentication
    @RequiresRoles("HR")
    public Result deleteDepartment(@RequestBody Department department) {
        Department departmentFound = departmentService.findByDepartmentId(department.getDepartmentId());
        if (departmentFound == null) {
            return Result.error("要删除的部门不存在");
        }

        departmentFound.setUsable(false);
        departmentService.update(departmentFound);
        return Result.success("部门已删除");
    }

    /**
     * 按传入的 departmentId 修改部门名
     *
     * @param department 部门对象，必须包含 departmentId 和 departmentName
     * @return 结果对象
     */
    @PostMapping("/modifyDepartment")
    @RequiresAuthentication
    @RequiresRoles("HR")
    public Result modifyDepartment(@RequestBody Department department) {
        if (StrUtil.isBlank(department.getDepartmentName())) {
            return Result.error("没有指定部门名，无法修改部门");
        }

        Department departmentFound = departmentService.findByDepartmentId(department.getDepartmentId());
        if (departmentFound == null) {
            return Result.error("要修改的部门不存在");
        }

        departmentFound.setDepartmentName(department.getDepartmentName());
        departmentService.update(departmentFound);
        return Result.success("部门名修改成功");
    }

    /**
     * 按 部门 id 获取部门人数
     *
     * @param department 部门对象，必须包含 departmentId
     * @return 结果对象，包含部门人数
     */
    @PostMapping("/getDepartmentEmployeesCount")
    @RequiresAuthentication
    public Result getDepartmentEmployeesCount(@RequestBody Department department) {
        Department departmentFound = departmentService.findByDepartmentId(department.getDepartmentId());
        if (departmentFound == null) {
            return Result.error("查询的部门不存在");
        }

        return userCompanyService.countEmployeesByDepartmentId(department.getDepartmentId());
    }

    /**
     * 按 公司 id 获取各部门人数，以饼图数据返回
     *
     * @param requestWithLongDto 必须包含一个 公司 id
     * @return 结果对象，包含一个饼图数据对象，示例：
     *
     * {
     *     "code": 200,
     *     "msg": "各部门人数查找成功",
     *     "data": {
     *         "data": [
     *             { "name": "新部门1", "value": 4 },
     *             { "name": "新部门2", "value": 2 },
     *             { "name": "新部门3", "value": 1 },
     *             { "name": "新部门4", "value": 0 }
     *         ]
     *     }
     * }
     */
    @PostMapping("/getDepartmentsEmployeesCount")
//    @RequiresAuthentication
    public Result getDepartmentsEmployeesCount(@Validated @RequestBody RequestWithLongDto requestWithLongDto) {
        Long companyId = requestWithLongDto.getId();
        Result findCompanyResult = companyService.find(companyId);
        if (findCompanyResult.getCode() != 200) {
            return Result.error("公司不存在，查询公司各部门人数失败");
        }

        Result listDepartmentsResult = departmentService.listDepartments(companyId);
        List<Department> departments = (List<Department>) listDepartmentsResult.getData();

        ResponseWithPieDataDto<Long> responseWithPieDataDtos = new ResponseWithPieDataDto<>();
        List<NameValue<Long>> nameValues = new ArrayList<>();

        for (Department department : departments) {
            NameValue<Long> nameValue = new NameValue<>();
            Result countResult = userCompanyService.countEmployeesByDepartmentId(department.getDepartmentId());
            Long count = (Long) countResult.getData();

            nameValue.setName(department.getDepartmentName());
            nameValue.setValue(count);

            nameValues.add(nameValue);
        }

        responseWithPieDataDtos.setData(nameValues);
        return Result.success("各部门人数查找成功", responseWithPieDataDtos);
    }
}
